#include "bemfaclient.h"
#include "../utils/logger.h"
#include <QJsonArray>
#include <QtMath>

BemfaClient::BemfaClient(QObject *parent)
    : QObject(parent), m_socket(nullptr), m_heartbeatTimer(nullptr), m_dataPushTimer(nullptr), m_fullDataUploadTimer(nullptr), m_reconnectTimer(nullptr), m_connected(false), m_subscribed(false), m_bytesSent(0), m_bytesReceived(0), m_reconnectAttempts(0), m_deviceManager(nullptr), m_alarmEngine(nullptr)
{
    // 创建TCP套接字
    m_socket = new QTcpSocket(this);
    connect(m_socket, &QTcpSocket::connected, this, &BemfaClient::onConnected);
    connect(m_socket, &QTcpSocket::disconnected, this, &BemfaClient::onDisconnected);
    connect(m_socket, &QTcpSocket::errorOccurred, this, &BemfaClient::onSocketError);
    connect(m_socket, &QTcpSocket::readyRead, this, &BemfaClient::onReadyRead);

    // 创建心跳定时器（60秒）
    m_heartbeatTimer = new QTimer(this);
    m_heartbeatTimer->setInterval(60000); // 60秒
    connect(m_heartbeatTimer, &QTimer::timeout, this, &BemfaClient::sendHeartbeat);

    // 创建数据推送定时器
    m_dataPushTimer = new QTimer(this);
    connect(m_dataPushTimer, &QTimer::timeout, this, &BemfaClient::autoPushData);

    // 创建全量数据上传定时器
    m_fullDataUploadTimer = new QTimer(this);
    connect(m_fullDataUploadTimer, &QTimer::timeout, this, &BemfaClient::autoUploadFullData);

    // 创建重连定时器
    m_reconnectTimer = new QTimer(this);
    m_reconnectTimer->setSingleShot(true);
    connect(m_reconnectTimer, &QTimer::timeout, this, &BemfaClient::performReconnect);

    setStatus("未连接");
}

BemfaClient::~BemfaClient()
{
    disconnectFromServer();
}

bool BemfaClient::initialize(const QString &host, int port, const QString &uid)
{
    m_host = host;
    m_port = port;
    m_uid = uid;

    if (m_uid.isEmpty())
    {
        Logger::instance()->error("BemfaClient", "用户私钥为空，无法初始化");
        return false;
    }

    Logger::instance()->info("BemfaClient", QString("初始化完成，服务器：%1:%2").arg(m_host).arg(m_port));
    return true;
}

void BemfaClient::setDeviceManager(DeviceManager *deviceManager)
{
    m_deviceManager = deviceManager;
}

void BemfaClient::setAlarmEngine(AlarmEngine *alarmEngine)
{
    if (m_alarmEngine)
    {
        // 断开之前的连接
        disconnect(m_alarmEngine, &AlarmEngine::alarmTriggered, this, &BemfaClient::onAlarmTriggered);
    }

    m_alarmEngine = alarmEngine;

    if (m_alarmEngine)
    {
        // 连接报警信号
        connect(m_alarmEngine, &AlarmEngine::alarmTriggered, this, &BemfaClient::onAlarmTriggered);
    }
}

void BemfaClient::addRoomConfig(const RoomInfo &roomInfo)
{
    m_roomConfigs.append(roomInfo);
    Logger::instance()->info("BemfaClient",
                             QString("添加配电室配置：%1 -> 主题：%2，电表范围：%3-%4")
                                 .arg(roomInfo.roomName)
                                 .arg(roomInfo.topic)
                                 .arg(roomInfo.startMeterId)
                                 .arg(roomInfo.endMeterId));
}

void BemfaClient::connectToServer()
{
    if (m_connected)
    {
        Logger::instance()->warning("BemfaClient", "已经连接到服务器");
        return;
    }

    if (m_host.isEmpty() || m_port <= 0)
    {
        Logger::instance()->error("BemfaClient", "服务器地址或端口未配置");
        emit errorOccurred("服务器地址或端口未配置");
        return;
    }

    setStatus("正在连接...");
    Logger::instance()->info("BemfaClient", QString("正在连接到 %1:%2").arg(m_host).arg(m_port));
    m_socket->connectToHost(m_host, m_port);
}

void BemfaClient::disconnectFromServer()
{
    if (m_socket->state() == QAbstractSocket::ConnectedState)
    {
        Logger::instance()->info("BemfaClient", "断开连接");
        m_socket->disconnectFromHost();
    }

    // 停止所有定时器
    if (m_heartbeatTimer->isActive())
        m_heartbeatTimer->stop();
    if (m_dataPushTimer->isActive())
        m_dataPushTimer->stop();
    if (m_fullDataUploadTimer->isActive())
        m_fullDataUploadTimer->stop();
    if (m_reconnectTimer->isActive())
        m_reconnectTimer->stop();

    m_connected = false;
    m_subscribed = false;
    setStatus("未连接");
    emit connectedChanged();
}

void BemfaClient::startAutoPush(int dataPushInterval, int fullDataUploadInterval)
{
    // 启动数据推送定时器
    m_dataPushTimer->setInterval(dataPushInterval * 1000);
    m_dataPushTimer->start();
    Logger::instance()->info("BemfaClient", QString("启动自动推送，数据间隔：%1秒").arg(dataPushInterval));

    // 启动全量数据上传定时器
    m_fullDataUploadTimer->setInterval(fullDataUploadInterval * 1000);
    m_fullDataUploadTimer->start();
    Logger::instance()->info("BemfaClient", QString("启动全量数据上传，间隔：%1秒").arg(fullDataUploadInterval));
}

void BemfaClient::stopAutoPush()
{
    if (m_dataPushTimer->isActive())
        m_dataPushTimer->stop();
    if (m_fullDataUploadTimer->isActive())
        m_fullDataUploadTimer->stop();

    Logger::instance()->info("BemfaClient", "停止自动推送");
}

bool BemfaClient::subscribe(const QString &topics)
{
    if (!m_connected)
    {
        Logger::instance()->error("BemfaClient", "未连接到服务器，无法订阅");
        return false;
    }

    // 格式：cmd=1&uid=xxx&topic=xxx1,xxx2,xxx3\r\n
    QString command = QString("cmd=1&uid=%1&topic=%2\r\n").arg(m_uid).arg(topics);
    bool success = sendCommand(command);

    if (success)
    {
        // 记录订阅的主题列表，用于订阅成功时回显
        m_subscribedTopics = topics;
        Logger::instance()->info("BemfaClient", QString("发送订阅请求：%1").arg(topics));
    }

    return success;
}

bool BemfaClient::publish(const QString &topic, const QString &message)
{
    if (!m_connected)
    {
        Logger::instance()->warning("BemfaClient", "未连接到服务器，无法发布消息");
        return false;
    }

    // 格式：cmd=2&uid=xxx&topic=xxx&msg=xxx\r\n
    QString command = QString("cmd=2&uid=%1&topic=%2&msg=%3\r\n")
                          .arg(m_uid)
                          .arg(topic)
                          .arg(message);

    Logger::instance()->debug("BemfaClient",
                              QString("发布 [%1]: %2").arg(topic).arg(message.length() > 50 ? message.left(50) + "..." : message));

    // 在发送前记录主题，确保能正确关联响应
    // 注意：对于带后缀的主题（如/up、/set），服务器可能返回不同的主题名
    m_lastPublishedTopic = topic;

    return sendCommand(command);
}

bool BemfaClient::publishJson(const QString &topic, const QJsonObject &jsonData)
{
    QJsonDocument doc(jsonData);
    QString jsonString = doc.toJson(QJsonDocument::Compact);

    // 调试日志：显示推送的JSON内容
    Logger::instance()->debug("BemfaClient",
                              QString("推送JSON [%1]: %2").arg(topic).arg(jsonString));

    return publish(topic, jsonString);
}

void BemfaClient::pushRoomSummary(int roomId)
{
    if (!m_deviceManager)
    {
        Logger::instance()->warning("BemfaClient", "设备管理器未设置，无法推送数据");
        return;
    }

    if (roomId == 0)
    {
        // 推送所有配电室
        for (const RoomInfo &room : m_roomConfigs)
        {
            QJsonObject summaryData = generateRoomSummary(room.roomId);
            publishJson(room.topic, summaryData);
        }
    }
    else
    {
        // 推送指定配电室
        QJsonObject summaryData = generateRoomSummary(roomId);
        QString topic = getRoomTopic(roomId);
        if (!topic.isEmpty())
        {
            publishJson(topic, summaryData);
        }
    }
}

void BemfaClient::uploadFullData(int roomId)
{
    if (!m_deviceManager)
    {
        Logger::instance()->warning("BemfaClient", "设备管理器未设置，无法上传数据");
        return;
    }

    if (roomId == 0)
    {
        // 上传所有配电室
        for (const RoomInfo &room : m_roomConfigs)
        {
            // 获取该配电室的所有电表
            for (int meterId = room.startMeterId; meterId <= room.endMeterId; ++meterId)
            {
                Meter *meter = m_deviceManager->getMeter(meterId);
                if (meter && meter->isOnline())
                {
                    QJsonObject meterData = generateMeterData(meter);
                    // 使用/up后缀，只更新云端数据，不推送
                    publishJson(room.topic + "/up", meterData);
                }
            }
        }
    }
    else
    {
        // 上传指定配电室
        QString topic = getRoomTopic(roomId);
        if (topic.isEmpty())
            return;

        for (const RoomInfo &room : m_roomConfigs)
        {
            if (room.roomId == roomId)
            {
                for (int meterId = room.startMeterId; meterId <= room.endMeterId; ++meterId)
                {
                    Meter *meter = m_deviceManager->getMeter(meterId);
                    if (meter && meter->isOnline())
                    {
                        QJsonObject meterData = generateMeterData(meter);
                        publishJson(topic + "/up", meterData);
                    }
                }
                break;
            }
        }
    }
}

void BemfaClient::onConnected()
{
    m_connected = true;
    m_reconnectAttempts = 0;
    setStatus("已连接");

    Logger::instance()->info("BemfaClient", "成功连接到巴法云服务器");
    emit connectedChanged();
    emit connectionEstablished();

    // 启动心跳定时器
    m_heartbeatTimer->start();

    // 订阅所有配电室主题
    QStringList topicList;
    for (const RoomInfo &room : m_roomConfigs)
    {
        topicList.append(room.topic);
    }

    if (!topicList.isEmpty())
    {
        QString topics = topicList.join(",");
        subscribe(topics);
    }
}

void BemfaClient::onDisconnected()
{
    bool wasConnected = m_connected;
    m_connected = false;
    m_subscribed = false;
    setStatus("连接断开");

    // 停止心跳
    if (m_heartbeatTimer->isActive())
        m_heartbeatTimer->stop();

    Logger::instance()->warning("BemfaClient", "与服务器断开连接");
    emit connectedChanged();
    if (wasConnected)
    {
        emit connectionLost();
    }

    // 启动重连机制
    startReconnectTimer();
}

void BemfaClient::onSocketError(QAbstractSocket::SocketError error)
{
    QString errorString = m_socket->errorString();
    Logger::instance()->error("BemfaClient", QString("Socket错误：%1 (%2)").arg(errorString).arg(error));
    emit errorOccurred(errorString);

    // 如果不是正在连接状态，启动重连
    if (error != QAbstractSocket::SocketTimeoutError)
    {
        startReconnectTimer();
    }
}

void BemfaClient::onReadyRead()
{
    QByteArray data = m_socket->readAll();
    m_bytesReceived += data.size();
    emit bytesReceivedChanged();

    // 追加到接收缓冲区
    m_receiveBuffer.append(QString::fromUtf8(data));

    // 处理粘包：按\r\n分割
    while (m_receiveBuffer.contains("\r\n"))
    {
        int pos = m_receiveBuffer.indexOf("\r\n");
        QString message = m_receiveBuffer.left(pos);
        m_receiveBuffer.remove(0, pos + 2);

        if (!message.isEmpty())
        {
            parseReceivedData(message);
        }
    }
}

void BemfaClient::sendHeartbeat()
{
    if (!m_connected)
        return;

    // 发送心跳：ping\r\n
    sendCommand("ping\r\n");
}

void BemfaClient::autoPushData()
{
    if (!m_connected)
        return;

    // 推送所有配电室的汇总数据
    pushRoomSummary(0);
}

void BemfaClient::autoUploadFullData()
{
    if (!m_connected)
        return;

    // 上传所有配电室的全量数据
    uploadFullData(0);
}

void BemfaClient::onAlarmTriggered(const AlarmEvent &event)
{
    if (!m_connected)
        return;

    // 根据电表ID确定配电室
    int roomId = getRoomIdByMeterId(event.meterId);
    if (roomId == 0)
        return;

    QString topic = getRoomTopic(roomId);
    if (topic.isEmpty())
        return;

    // 生成报警JSON数据
    QJsonObject alarmData = generateAlarmData(event);

    // 立即推送报警（不使用/up后缀）
    publishJson(topic, alarmData);

    Logger::instance()->warning("BemfaClient",
                                QString("推送报警到主题 %1：%2").arg(topic).arg(event.description()));
}

void BemfaClient::performReconnect()
{
    m_reconnectAttempts++;

    Logger::instance()->info("BemfaClient",
                             QString("尝试重连 (第 %1 次)...").arg(m_reconnectAttempts));

    connectToServer();
}

bool BemfaClient::sendCommand(const QString &command)
{
    if (m_socket->state() != QAbstractSocket::ConnectedState)
    {
        return false;
    }

    QByteArray data = command.toUtf8();
    qint64 written = m_socket->write(data);

    if (written > 0)
    {
        m_bytesSent += written;
        emit bytesSentChanged();
        return true;
    }

    return false;
}

void BemfaClient::parseReceivedData(const QString &data)
{
    // 解析服务器返回的消息
    // 格式：cmd=x&res=x 或 cmd=x&topic=xxx&msg=xxx

    // 添加调试日志：显示原始响应
    Logger::instance()->debug("BemfaClient", QString("收到响应: %1").arg(data));

    QString cmd = extractValue(data, "cmd");
    QString res = extractValue(data, "res");
    QString topic = extractValue(data, "topic");
    QString msg = extractValue(data, "msg");

    if (cmd == "0")
    {
        // 心跳响应 (cmd=0&res=1)
        if (res == "1")
        {
            Logger::instance()->debug("BemfaClient", "心跳正常");
        }
        else
        {
            Logger::instance()->warning("BemfaClient", "心跳异常");
        }
    }
    else if (cmd == "1")
    {
        // 订阅响应 (cmd=1&res=1)
        if (res == "1")
        {
            m_subscribed = true;
            // 订阅成功时，服务器返回的响应中没有topic字段
            // 需要从之前发送的订阅命令中获取主题列表
            Logger::instance()->info("BemfaClient", "订阅成功");
            emit subscribeSucceeded(m_subscribedTopics); // 使用记录的主题列表
        }
        else if (res == "0")
        {
            Logger::instance()->error("BemfaClient", "订阅失败：服务器返回错误");
        }
        else
        {
            Logger::instance()->error("BemfaClient", QString("订阅失败：未知响应 res=%1").arg(res));
        }
    }
    else if (cmd == "2")
    {
        // 发布响应
        // 巴法云返回机制（已通过测试验证）：
        // 1. 先返回消息回显：cmd=2&uid=xxx&topic=xxx&msg=xxx（无res字段）
        // 2. 再返回结果确认：cmd=2&res=1（无topic和msg字段）
        if (res.isEmpty() && !topic.isEmpty() && !msg.isEmpty())
        {
            // 这是消息回显
            // 注意：对于带后缀的主题（/up、/set），服务器可能返回不同的主题名
            // 因此只在必要时更新（当m_lastPublishedTopic为空时）
            if (m_lastPublishedTopic.isEmpty())
            {
                m_lastPublishedTopic = topic;
            }
            Logger::instance()->debug("BemfaClient",
                                      QString("消息回显 [%1]: %2").arg(topic).arg(msg.length() > 50 ? msg.left(50) + "..." : msg));
        }
        else if (res == "1")
        {
            // 发布成功确认（使用记录的主题）
            Logger::instance()->info("BemfaClient",
                                     QString("✓ 发布成功 [%1]").arg(m_lastPublishedTopic));
            emit publishSucceeded(m_lastPublishedTopic);
            m_lastPublishedTopic.clear(); // 清空记录
        }
        else if (res == "0")
        {
            // 发布失败
            Logger::instance()->error("BemfaClient",
                                      QString("✗ 发布失败 [%1]").arg(m_lastPublishedTopic));
            m_lastPublishedTopic.clear();
        }
        else if (!res.isEmpty())
        {
            // 其他错误
            Logger::instance()->error("BemfaClient",
                                      QString("✗ 发布异常 (res=%1)").arg(res));
        }
    }
    else if (!cmd.isEmpty() && !topic.isEmpty() && !msg.isEmpty())
    {
        // 收到推送的消息（其他设备发布的消息）
        Logger::instance()->info("BemfaClient",
                                 QString("收到推送 [%1]: %2").arg(topic).arg(msg));
        emit messageReceived(topic, msg);
    }
    else
    {
        // 未识别的响应
        Logger::instance()->warning("BemfaClient",
                                    QString("未识别的响应: %1").arg(data));
    }
}

QString BemfaClient::extractValue(const QString &data, const QString &key) const
{
    // 从键值对字符串中提取值
    // 格式：key1=value1&key2=value2

    QString pattern = key + "=";
    int startPos = data.indexOf(pattern);
    if (startPos == -1)
        return QString();

    startPos += pattern.length();
    int endPos = data.indexOf("&", startPos);

    if (endPos == -1)
    {
        // 最后一个键值对
        return data.mid(startPos);
    }
    else
    {
        return data.mid(startPos, endPos - startPos);
    }
}

QJsonObject BemfaClient::generateRoomSummary(int roomId)
{
    QJsonObject summary;

    // 查找配电室配置
    const RoomInfo *roomInfo = nullptr;
    for (const RoomInfo &room : m_roomConfigs)
    {
        if (room.roomId == roomId)
        {
            roomInfo = &room;
            break;
        }
    }

    if (!roomInfo || !m_deviceManager)
        return summary;

    // 统计数据
    int onlineCount = 0;
    int offlineCount = 0;
    double totalPower = 0.0;
    double totalCurrent = 0.0;
    int alarmCount = 0;

    // 遍历该配电室的所有电表
    for (int meterId = roomInfo->startMeterId; meterId <= roomInfo->endMeterId; ++meterId)
    {
        Meter *meter = m_deviceManager->getMeter(meterId);
        if (meter)
        {
            if (meter->isOnline())
            {
                onlineCount++;
                totalPower += meter->totalPower();
                totalCurrent += meter->averageCurrent();
            }
            else
            {
                offlineCount++;
            }
        }
    }

    // 获取报警数量
    if (m_alarmEngine)
    {
        QVector<AlarmEvent> activeAlarms = m_alarmEngine->getActiveAlarms();
        for (const AlarmEvent &alarm : activeAlarms)
        {
            if (alarm.meterId >= roomInfo->startMeterId && alarm.meterId <= roomInfo->endMeterId)
            {
                alarmCount++;
            }
        }
    }

    // 构建精简JSON对象（巴法云限制消息长度）
    summary["on"] = onlineCount;                                     // 在线数
    summary["off"] = offlineCount;                                   // 离线数
    summary["p"] = QString::number(totalPower, 'f', 1).toDouble();   // 总功率
    summary["i"] = QString::number(totalCurrent, 'f', 1).toDouble(); // 总电流
    summary["a"] = alarmCount;                                       // 报警数
    summary["s"] = (alarmCount > 0) ? 1 : 0;                         // 状态：0正常，1报警

    return summary;
}

QJsonObject BemfaClient::generateMeterData(Meter *meter)
{
    if (!meter)
        return QJsonObject();

    // 精简格式（巴法云限制消息长度）
    QJsonObject data;
    data["id"] = meter->meterId();
    data["ua"] = QString::number(meter->ua(), 'f', 1).toDouble();
    data["ub"] = QString::number(meter->ub(), 'f', 1).toDouble();
    data["uc"] = QString::number(meter->uc(), 'f', 1).toDouble();
    data["ia"] = QString::number(meter->ia(), 'f', 1).toDouble();
    data["ib"] = QString::number(meter->ib(), 'f', 1).toDouble();
    data["ic"] = QString::number(meter->ic(), 'f', 1).toDouble();

    return data;
}

QJsonObject BemfaClient::generateAlarmData(const AlarmEvent &event)
{
    // 精简格式（巴法云限制消息长度）
    QJsonObject data;
    data["t"] = "alarm";                                              // 类型
    data["id"] = event.meterId;                                       // 电表ID
    data["v"] = QString::number(event.value, 'f', 1).toDouble();      // 当前值
    data["th"] = QString::number(event.threshold, 'f', 0).toDouble(); // 阈值
    data["type"] = static_cast<int>(event.type);                      // 报警类型编号

    return data;
}

QString BemfaClient::getRoomTopic(int roomId) const
{
    for (const RoomInfo &room : m_roomConfigs)
    {
        if (room.roomId == roomId)
        {
            return room.topic;
        }
    }
    return QString();
}

int BemfaClient::getRoomIdByMeterId(int meterId) const
{
    for (const RoomInfo &room : m_roomConfigs)
    {
        if (meterId >= room.startMeterId && meterId <= room.endMeterId)
        {
            return room.roomId;
        }
    }
    return 0;
}

void BemfaClient::startReconnectTimer()
{
    // 使用指数退避策略
    // 重连间隔：2, 4, 8, 16, 32, 60, 60, 60...秒
    int interval = qMin(static_cast<int>(qPow(2.0, m_reconnectAttempts)), 60) * 1000;

    setStatus(QString("等待重连... (%1秒后)").arg(interval / 1000));
    Logger::instance()->info("BemfaClient", QString("将在 %1 秒后重连").arg(interval / 1000));

    m_reconnectTimer->setInterval(interval);
    m_reconnectTimer->start();
}

void BemfaClient::setStatus(const QString &status)
{
    if (m_status != status)
    {
        m_status = status;
        emit statusChanged();
    }
}
